// SPDX-FileCopyrightText: Copyright 2025-2025 深圳市同心圆网络有限公司
// SPDX-License-Identifier: Apache-2.0

package resource_card_api_serv

import (
	"context"
	"math"
	"time"

	"gitcode.com/lvupclub/lvup-api/dao"
	"gitcode.com/lvupclub/lvup-api/dao/resource_dao"
	"gitcode.com/lvupclub/proto-gen-go.git/src/resource_api"
	"gitcode.com/lvupclub/proto-gen-go.git/src/resource_card_api"
	"github.com/google/uuid"
)

func (apiImpl *ResourceCardApiImpl) Create(ctx context.Context, req *resource_card_api.CreateRequest) (*resource_card_api.CreateResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &resource_card_api.CreateResponse{
			Code:   resource_card_api.CreateResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	resourceItem, err := resource_dao.ResourceInfoDao.Get(ctx, req.ResourceId)
	if err != nil {
		return &resource_card_api.CreateResponse{
			Code:   resource_card_api.CreateResponse_CODE_NO_RESOURCE,
			ErrMsg: "资料库不存在",
		}, nil
	}
	if resourceItem.ResourceType != resource_api.RESOURCE_TYPE_RESOURCE_TYPE_CARD || resourceItem.OwnerUserId != sessItem.UserId {
		return &resource_card_api.CreateResponse{
			Code:   resource_card_api.CreateResponse_CODE_NO_RESOURCE,
			ErrMsg: "资料库不存在",
		}, nil
	}

	cardId := uuid.NewString()
	nowTime := time.Now().UnixMilli()

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx context.Context) (interface{}, error) {
		err = resource_dao.CardInfoDao.Insert(sessCtx, &resource_dao.CardInfoDbItem{
			CardId:     cardId,
			ResourceId: req.ResourceId,
			BasicInfo: resource_dao.BasicCardInfoDbItem{
				Title:   req.BasicInfo.Title,
				Content: req.BasicInfo.Content,
			},
			CreateTime: nowTime,
			UpdateTime: nowTime,
		})
		if err != nil {
			return nil, err
		}
		return &resource_card_api.CreateResponse{
			Code:   resource_card_api.CreateResponse_CODE_OK,
			CardId: cardId,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*resource_card_api.CreateResponse), nil
}

func (apiImpl *ResourceCardApiImpl) UpdateBasic(ctx context.Context, req *resource_card_api.UpdateBasicRequest) (*resource_card_api.UpdateBasicResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &resource_card_api.UpdateBasicResponse{
			Code:   resource_card_api.UpdateBasicResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	resourceItem, err := resource_dao.ResourceInfoDao.Get(ctx, req.ResourceId)
	if err != nil {
		return &resource_card_api.UpdateBasicResponse{
			Code:   resource_card_api.UpdateBasicResponse_CODE_NO_RESOURCE,
			ErrMsg: "资料库不存在",
		}, nil
	}
	if resourceItem.ResourceType != resource_api.RESOURCE_TYPE_RESOURCE_TYPE_CARD || resourceItem.OwnerUserId != sessItem.UserId {
		return &resource_card_api.UpdateBasicResponse{
			Code:   resource_card_api.UpdateBasicResponse_CODE_NO_RESOURCE,
			ErrMsg: "资料库不存在",
		}, nil
	}
	exist, err := resource_dao.CardInfoDao.Exist(ctx, req.ResourceId, req.CardId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &resource_card_api.UpdateBasicResponse{
			Code:   resource_card_api.UpdateBasicResponse_CODE_NO_CARD,
			ErrMsg: "知识卡片不存在",
		}, nil
	}

	nowTime := time.Now().UnixMilli()

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx context.Context) (interface{}, error) {
		err = resource_dao.CardInfoDao.UpdateBasic(sessCtx, req.ResourceId, req.CardId, &resource_dao.BasicCardInfoDbItem{
			Title:   req.BasicInfo.Title,
			Content: req.BasicInfo.Content,
		}, nowTime)
		if err != nil {
			return nil, err
		}
		return &resource_card_api.UpdateBasicResponse{
			Code: resource_card_api.UpdateBasicResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*resource_card_api.UpdateBasicResponse), nil
}

func (apiImpl *ResourceCardApiImpl) Remove(ctx context.Context, req *resource_card_api.RemoveRequest) (*resource_card_api.RemoveResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &resource_card_api.RemoveResponse{
			Code:   resource_card_api.RemoveResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	resourceItem, err := resource_dao.ResourceInfoDao.Get(ctx, req.ResourceId)
	if err != nil {
		return &resource_card_api.RemoveResponse{
			Code:   resource_card_api.RemoveResponse_CODE_NO_RESOURCE,
			ErrMsg: "资料库不存在",
		}, nil
	}
	if resourceItem.ResourceType != resource_api.RESOURCE_TYPE_RESOURCE_TYPE_CARD || resourceItem.OwnerUserId != sessItem.UserId {
		return &resource_card_api.RemoveResponse{
			Code:   resource_card_api.RemoveResponse_CODE_NO_RESOURCE,
			ErrMsg: "资料库不存在",
		}, nil
	}
	exist, err := resource_dao.CardInfoDao.Exist(ctx, req.ResourceId, req.CardId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &resource_card_api.RemoveResponse{
			Code: resource_card_api.RemoveResponse_CODE_OK,
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx context.Context) (interface{}, error) {
		err = resource_dao.CardInfoDao.Remove(sessCtx, req.ResourceId, req.CardId)
		if err != nil {
			return nil, err
		}
		err = resource_dao.CardLinkDao.RemoveByCard(sessCtx, req.ResourceId, req.CardId)
		if err != nil {
			return nil, err
		}
		err = resource_dao.CardStateDao.RemoveByCard(sessCtx, req.ResourceId, req.CardId)
		if err != nil {
			return nil, err
		}
		return &resource_card_api.RemoveResponse{
			Code: resource_card_api.RemoveResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*resource_card_api.RemoveResponse), nil
}

func (apiImpl *ResourceCardApiImpl) List(ctx context.Context, req *resource_card_api.ListRequest) (*resource_card_api.ListResponse, error) {
	emptyList := []*resource_card_api.CardInfo{}

	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &resource_card_api.ListResponse{
			Code:     resource_card_api.ListResponse_CODE_WRONG_SESSION,
			ErrMsg:   "会话不存在",
			CardList: emptyList,
		}, nil
	}
	resourceItem, err := resource_dao.ResourceInfoDao.Get(ctx, req.ResourceId)
	if err != nil {
		return &resource_card_api.ListResponse{
			Code:     resource_card_api.ListResponse_CODE_NO_RESOURCE,
			ErrMsg:   "资料库不存在",
			CardList: emptyList,
		}, nil
	}
	if resourceItem.ResourceType != resource_api.RESOURCE_TYPE_RESOURCE_TYPE_CARD || resourceItem.OwnerUserId != sessItem.UserId {
		return &resource_card_api.ListResponse{
			Code:     resource_card_api.ListResponse_CODE_NO_RESOURCE,
			ErrMsg:   "资料库不存在",
			CardList: emptyList,
		}, nil
	}
	count, err := resource_dao.CardInfoDao.Count(ctx, req.ResourceId, req.FilterByKeyword, req.Keyword, false, []string{})
	if err != nil {
		return nil, err
	}
	cardItemList, err := resource_dao.CardInfoDao.List(ctx, req.ResourceId, req.FilterByKeyword, req.Keyword, false, []string{}, int64(req.Offset), int64(req.Limit))
	if err != nil {
		return nil, err
	}
	cardList, err := apiImpl.completeCardList(ctx, req.ResourceId, cardItemList, req.WithContent)
	if err != nil {
		return nil, err
	}
	return &resource_card_api.ListResponse{
		Code:       resource_card_api.ListResponse_CODE_OK,
		TotalCount: count,
		CardList:   cardList,
	}, nil
}

func (apiImpl *ResourceCardApiImpl) Get(ctx context.Context, req *resource_card_api.GetRequest) (*resource_card_api.GetResponse, error) {
	emptyInfo := &resource_card_api.CardInfo{
		BasicInfo: &resource_card_api.BasicCardInfo{},
		LinkList:  []*resource_card_api.ReleateCardLink{},
	}

	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &resource_card_api.GetResponse{
			Code:   resource_card_api.GetResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
			Card:   emptyInfo,
		}, nil
	}
	resourceItem, err := resource_dao.ResourceInfoDao.Get(ctx, req.ResourceId)
	if err != nil {
		return &resource_card_api.GetResponse{
			Code:   resource_card_api.GetResponse_CODE_NO_RESOURCE,
			ErrMsg: "资料库不存在",
			Card:   emptyInfo,
		}, nil
	}
	if resourceItem.ResourceType != resource_api.RESOURCE_TYPE_RESOURCE_TYPE_CARD || resourceItem.OwnerUserId != sessItem.UserId {
		return &resource_card_api.GetResponse{
			Code:   resource_card_api.GetResponse_CODE_NO_RESOURCE,
			ErrMsg: "资料库不存在",
			Card:   emptyInfo,
		}, nil
	}

	cardItem, err := resource_dao.CardInfoDao.Get(ctx, req.ResourceId, req.CardId)
	if err != nil {
		return &resource_card_api.GetResponse{
			Code:   resource_card_api.GetResponse_CODE_NO_RESOURCE,
			ErrMsg: "知识卡不存在",
			Card:   emptyInfo,
		}, nil
	}
	cardList, err := apiImpl.completeCardList(ctx, req.ResourceId, []*resource_dao.CardInfoDbItem{cardItem}, true)
	if err != nil {
		return nil, err
	}
	if len(cardList) == 0 {
		return &resource_card_api.GetResponse{
			Code:   resource_card_api.GetResponse_CODE_NO_RESOURCE,
			ErrMsg: "知识卡不存在",
			Card:   emptyInfo,
		}, nil
	}
	return &resource_card_api.GetResponse{
		Code: resource_card_api.GetResponse_CODE_OK,
		Card: cardList[0],
	}, nil
}

func (apiImpl *ResourceCardApiImpl) completeCardList(ctx context.Context, resourceId string, cardItemList []*resource_dao.CardInfoDbItem, withContent bool) ([]*resource_card_api.CardInfo, error) {
	cardIdList := []string{}
	for _, cardItem := range cardItemList {
		cardIdList = append(cardIdList, cardItem.CardId)
	}
	//获取相关知识卡
	linkItemList, err := resource_dao.CardLinkDao.List(ctx, resourceId, cardIdList)
	if err != nil {
		return nil, err
	}

	targetCardIdList := []string{}
	for _, linkItem := range linkItemList {
		targetCardIdList = append(targetCardIdList, linkItem.CardId2)
	}
	targetCardItemList, err := resource_dao.CardInfoDao.List(ctx, resourceId, false, "", true, targetCardIdList, 0, math.MaxInt64)
	if err != nil {
		return nil, err
	}
	targetCardItemMap := map[string]*resource_dao.CardInfoDbItem{}
	for _, targetCardItem := range targetCardItemList {
		targetCardItemMap[targetCardItem.CardId] = targetCardItem
	}

	//生成结果
	cardList := []*resource_card_api.CardInfo{}
	for _, cardItem := range cardItemList {
		card := cardItem.ToCardInfo(withContent)
		card.LinkList = apiImpl.genLinkList(cardItem.CardId, linkItemList, targetCardItemMap)
		cardList = append(cardList, card)
	}
	return cardList, nil
}

func (apiImpl *ResourceCardApiImpl) genLinkList(cardId string, linkItemList []*resource_dao.CardLinkDbItem, cardItemMap map[string]*resource_dao.CardInfoDbItem) []*resource_card_api.ReleateCardLink {
	retList := []*resource_card_api.ReleateCardLink{}
	for _, linkItem := range linkItemList {
		if linkItem.CardId1 != cardId {
			continue
		}
		cardItem, ok := cardItemMap[linkItem.CardId2]
		if !ok {
			continue
		}
		retList = append(retList, &resource_card_api.ReleateCardLink{
			CardId: cardItem.CardId,
			Title:  cardItem.BasicInfo.Title,
		})
	}
	return retList
}

func (apiImpl *ResourceCardApiImpl) Link(ctx context.Context, req *resource_card_api.LinkRequest) (*resource_card_api.LinkResponse, error) {
	if req.CardId1 == req.CardId2 {
		return &resource_card_api.LinkResponse{
			Code:   resource_card_api.LinkResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &resource_card_api.LinkResponse{
			Code:   resource_card_api.LinkResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	resourceItem, err := resource_dao.ResourceInfoDao.Get(ctx, req.ResourceId)
	if err != nil {
		return &resource_card_api.LinkResponse{
			Code:   resource_card_api.LinkResponse_CODE_NO_RESOURCE,
			ErrMsg: "资料库不存在",
		}, nil
	}
	if resourceItem.ResourceType != resource_api.RESOURCE_TYPE_RESOURCE_TYPE_CARD || resourceItem.OwnerUserId != sessItem.UserId {
		return &resource_card_api.LinkResponse{
			Code:   resource_card_api.LinkResponse_CODE_NO_RESOURCE,
			ErrMsg: "资料库不存在",
		}, nil
	}
	exist, err := resource_dao.CardLinkDao.Exist(ctx, req.ResourceId, req.CardId1, req.CardId2)
	if err != nil {
		return nil, err
	}
	if exist {
		return &resource_card_api.LinkResponse{
			Code: resource_card_api.LinkResponse_CODE_OK,
		}, nil
	}

	exist, err = resource_dao.CardInfoDao.Exist(ctx, req.ResourceId, req.CardId1)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &resource_card_api.LinkResponse{
			Code:   resource_card_api.LinkResponse_CODE_NO_CARD,
			ErrMsg: "知识卡片不存在",
		}, nil
	}
	exist, err = resource_dao.CardInfoDao.Exist(ctx, req.ResourceId, req.CardId2)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &resource_card_api.LinkResponse{
			Code:   resource_card_api.LinkResponse_CODE_NO_CARD,
			ErrMsg: "知识卡片不存在",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx context.Context) (interface{}, error) {
		err = resource_dao.CardLinkDao.Insert(sessCtx, &resource_dao.CardLinkDbItem{
			ResourceId: req.ResourceId,
			CardId1:    req.CardId1,
			CardId2:    req.CardId2,
		})
		if err != nil {
			return nil, err
		}
		err = resource_dao.CardLinkDao.Insert(sessCtx, &resource_dao.CardLinkDbItem{
			ResourceId: req.ResourceId,
			CardId1:    req.CardId2,
			CardId2:    req.CardId1,
		})
		if err != nil {
			return nil, err
		}
		return &resource_card_api.LinkResponse{
			Code: resource_card_api.LinkResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*resource_card_api.LinkResponse), nil
}

func (apiImpl *ResourceCardApiImpl) Unlink(ctx context.Context, req *resource_card_api.UnlinkRequest) (*resource_card_api.UnlinkResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &resource_card_api.UnlinkResponse{
			Code:   resource_card_api.UnlinkResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	resourceItem, err := resource_dao.ResourceInfoDao.Get(ctx, req.ResourceId)
	if err != nil {
		return &resource_card_api.UnlinkResponse{
			Code:   resource_card_api.UnlinkResponse_CODE_NO_RESOURCE,
			ErrMsg: "资料库不存在",
		}, nil
	}
	if resourceItem.ResourceType != resource_api.RESOURCE_TYPE_RESOURCE_TYPE_CARD || resourceItem.OwnerUserId != sessItem.UserId {
		return &resource_card_api.UnlinkResponse{
			Code:   resource_card_api.UnlinkResponse_CODE_NO_RESOURCE,
			ErrMsg: "资料库不存在",
		}, nil
	}
	exist, err := resource_dao.CardLinkDao.Exist(ctx, req.ResourceId, req.CardId1, req.CardId2)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &resource_card_api.UnlinkResponse{
			Code: resource_card_api.UnlinkResponse_CODE_OK,
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx context.Context) (interface{}, error) {
		err = resource_dao.CardLinkDao.Remove(sessCtx, req.ResourceId, req.CardId1, req.CardId2)
		if err != nil {
			return nil, err
		}
		return &resource_card_api.UnlinkResponse{
			Code: resource_card_api.UnlinkResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*resource_card_api.UnlinkResponse), nil
}
